package com.feemanage.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cfg.domain.ClaimProjectShow;
import com.cfg.mapper.ClaimProjectShowMapper;
import com.common.core.domain.entity.SysUser;
import com.common.core.page.PageDomain;
import com.common.utils.SecurityUtils;
import com.common.utils.sql.SqlUtil;
import com.feemanage.common.SearchUtils;
import com.feemanage.domain.BizManageFee;
import com.feemanage.domain.BizProjectFeeCard;
import com.feemanage.domain.BizProjectIncome;
import com.feemanage.domain.bo.FundsFeeShowBo;
import com.feemanage.domain.bo.ProjectIncomeShowBo;
import com.feemanage.domain.vo.BizProjectInComeVo;
import com.feemanage.domain.vo.ClaimManageFeeVo;
import com.feemanage.domain.vo.ProjectIncomeShowVo;
import com.feemanage.mapper.bizClaimManageMapper;
import com.feemanage.mapper.bizManageFeeMapper;
import com.feemanage.mapper.bizProjectFeeCardMapper;
import com.feemanage.mapper.bizProjectIncomeMapper;
import com.feemanage.service.IBizProjectIncomeService;
import com.feemanage.service.ISysSnruleService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BizProjectIncomeServiceImpl implements IBizProjectIncomeService {

    @Autowired
    private bizProjectIncomeMapper baseMapper;

    @Autowired
    private ClaimProjectShowMapper projectShowMapper;

    @Autowired
    private bizClaimManageMapper manageMapper;

    @Autowired
    private bizManageFeeMapper manageFeeMapper ;

    @Autowired
    private bizProjectFeeCardMapper feeCardMapper ;


    @Autowired
    private cWIncomeServiceImpl incomeService;

    @Autowired
    private ISysSnruleService sysSnruleService;

    private final static String feeSchemeId = "2c97a35494de0ad60194fdf648120436"; //纵向项目-默认管理费方案
    private final static String project_Class_zX="zXProject"; // 纵向项目
    private final static String type_d="directIncome"; //直接入账

    /**
     * 查询列表
     * @param pageDomain
     * @param income
     * @return
     */
    @Override
    public IPage<BizProjectInComeVo> selectList(PageDomain pageDomain, BizProjectIncome income) {
        Page<BizProjectInComeVo> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
        QueryWrapper<BizProjectIncome> wrapper = getQuery(income);
        String orderByColumn = SqlUtil.escapeOrderBySql(pageDomain.getOrderByColumn());
        boolean isASC = SqlUtil.escapeOrderBySql(pageDomain.getIsAsc()).equalsIgnoreCase("asc");
        if (!StringUtils.isEmpty(orderByColumn))
        {
            wrapper.orderBy(true,isASC,orderByColumn);
        }
        return baseMapper.selectPageList(page,wrapper);
    }

    /**
     * 导出
     * @param income
     * @return
     */
    @Override
    public  List<BizProjectInComeVo> selectExportList(PageDomain pageDomain,BizProjectIncome income){
        QueryWrapper<BizProjectIncome> wrapper = getQuery(income);
        String orderByColumn = SqlUtil.escapeOrderBySql(pageDomain.getOrderByColumn());
        boolean isASC = SqlUtil.escapeOrderBySql(pageDomain.getIsAsc()).equalsIgnoreCase("asc");
        if (!StringUtils.isEmpty(orderByColumn))
        {
            wrapper.orderBy(true,isASC,orderByColumn);
        }
        return baseMapper.selectPageList(wrapper);
    }

    /**
     * 拼接条件
     * @param income
     * @return
     */
    private QueryWrapper<BizProjectIncome> getQuery(BizProjectIncome income) {
        Map<String, Object> params = income.getParams();
        QueryWrapper<BizProjectIncome> wrapper = Wrappers.query();
        wrapper.eq(StringUtils.isNotBlank(income.getProjectId()),"p.id", income.getProjectId())
                .like(StringUtils.isNotBlank(income.getFeeCardNum()), "c.fee_card_num", income.getFeeCardNum())
                .like(StringUtils.isNotBlank(income.getProjectName()),"p.name",income.getProjectName())
                .like(StringUtils.isNotBlank(income.getFeeChargerName()),"c.fee_charger_name",income.getFeeChargerName())
                .between(ObjectUtils.isNotEmpty(params.get("beginTime")) && ObjectUtils.isNotEmpty(params.get("endTime")),
                        "c.income_date", params.get("beginTime"), params.get("endTime"))
                .ge(ObjectUtils.isNotEmpty(params.get("beginTime")) && ObjectUtils.isEmpty(params.get("endTime")),"c.income_date", params.get("beginTime"))
                .le(ObjectUtils.isEmpty(params.get("beginTime")) && ObjectUtils.isNotEmpty(params.get("endTime")),"c.income_date", params.get("endTime"))
                .between(ObjectUtils.isNotEmpty(params.get("maxfee")) && ObjectUtils.isNotEmpty(params.get("minfee")),
                        "c.income_fee", SearchUtils.processAmount(params.get("minfee")), SearchUtils.processAmount(params.get("maxfee")))
                .ge(ObjectUtils.isNotEmpty(params.get("minfee")) && ObjectUtils.isEmpty(params.get("maxfee")),"c.income_fee", SearchUtils.processAmount(params.get("minfee")))
                .le(ObjectUtils.isNotEmpty(params.get("maxfee")) && ObjectUtils.isEmpty(params.get("minfee")),"c.income_fee", SearchUtils.processAmount(params.get("maxfee")))
                .like(StringUtils.isNotBlank(income.getIncomeUnitName()),"c.income_unit_name",income.getIncomeUnitName())
                .like(StringUtils.isNotBlank(income.getProjectCode()),"p.code",income.getProjectCode())
                .like(StringUtils.isNotBlank(income.getDch()),"c.dch",income.getDch())
                .in(StringUtils.isNotBlank(income.getIncomeType()),"c.income_type",income.getIncomeType())
                .eq("c.biz_type","cwIncomeClaim");
        if(StringUtils.isNotEmpty(income.getProjectType())){
            List<String> list = Arrays.stream(income.getProjectType().split(",")).collect(Collectors.toList());
            wrapper.in("p.project_type",list);
        }
        if(StringUtils.isNotEmpty(income.getUnitId())){
            List<String> list = Arrays.stream(income.getUnitId().split(",")).collect(Collectors.toList());
            wrapper.in("c.unit_id",list);
        }

        return wrapper;
    }

    /**
     * 新增
     * @param income
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean addProIncome(ProjectIncomeShowBo income) {
        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        BizProjectIncome projectIncome = new BizProjectIncome();
        BeanUtils.copyProperties(income,projectIncome);
        projectIncome.setIncomeDate(LocalDateTime.of(income.getIncomeDate(), LocalTime.MIN));
        projectIncome.setBizType(type_d);
        projectIncome.setChecker(loginUser.getNickName());
        projectIncome.setCheckdate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        if (StringUtils.isEmpty(income.getFeeCardNum()) || StringUtils.isBlank(income.getFeeCardNum())){
            String cardnum = sysSnruleService.generateCode("1",income.getProjectId());
            projectIncome.setFeeCardNum(cardnum);
        }
        Boolean flag =  baseMapper.insert(projectIncome) >0;
        insertFeeCard(projectIncome);
        return getaBoolean(income, projectIncome, flag);
    }

    /**
     * 编辑
     * @param income
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean editProIncome(ProjectIncomeShowBo income) {
        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        BizProjectIncome projectIncome = new BizProjectIncome();
        BeanUtils.copyProperties(income,projectIncome);
        projectIncome.setIncomeDate(LocalDateTime.of(income.getIncomeDate(), LocalTime.MIN));
        projectIncome.setChecker(loginUser.getNickName());
        projectIncome.setCheckdate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        Boolean flag =  baseMapper.updateById(projectIncome) >0;
        insertFeeCard(projectIncome);
        manageFeeMapper.delete(new QueryWrapper<BizManageFee>().in("INCOME_ID",income.getId()));
        return getaBoolean(income, projectIncome, flag);
    }

    /**
     * 判断是否要新增卡号
     * @param projectIncome
     */
    private void insertFeeCard(BizProjectIncome projectIncome){
        if(StringUtils.isNotEmpty(projectIncome.getFeeCardNum())){
           Long count = feeCardMapper.selectCount(new QueryWrapper<BizProjectFeeCard>().eq("FEE_CARD_NUM",projectIncome.getFeeCardNum()));
            if(count<=0){
                BizProjectFeeCard feeCard = new BizProjectFeeCard();
                feeCard.setProjectId(projectIncome.getProjectId());
                feeCard.setFeeCardNum(projectIncome.getFeeCardNum());
                feeCard.setFeeChargerCode(projectIncome.getFeeChargerCode());
                feeCard.setFeeChargerId(projectIncome.getFeeChargerId());
                feeCard.setFeeChargerName(projectIncome.getFeeChargerName());
                feeCard.setFeeChargerUnitId(projectIncome.getUnitId());
                feeCard.setTransferState("0");
                feeCardMapper.insert(feeCard);
            }
        }
    }

    /**
     * 插入管理费biz_manage_fee
     * @param income
     * @param projectIncome
     * @param flag
     * @return
     */
    private Boolean getaBoolean(ProjectIncomeShowBo income, BizProjectIncome projectIncome, Boolean flag) {
        if(flag && income.getProjectClass().equals(project_Class_zX)){
            List<BizManageFee> list = income.getManageFee();
            if (list!=null && !list.isEmpty()){
                for (BizManageFee manageFee:list){
                    BizManageFee bizManageFee = new BizManageFee();
                    BeanUtils.copyProperties(manageFee,bizManageFee);
                    bizManageFee.setProjectId(projectIncome.getProjectId());
                    bizManageFee.setFeeChargerId(projectIncome.getFeeChargerId());
                    bizManageFee.setFeeCardNum(projectIncome.getFeeCardNum());
                    bizManageFee.setIncomeId(projectIncome.getId());
                    bizManageFee.setBizType(projectIncome.getBizType());
                    manageFeeMapper.insert(bizManageFee);
                }
            }
        }
        return flag;
    }

    /**
     * 删除
     * @param ids
     * @param isValid
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean delProIncome(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        //先删从表,如果是纵向项目，没有管理费
        manageFeeMapper.delete(new QueryWrapper<BizManageFee>().in("INCOME_ID",ids));
        feeCardMapper.delete(new QueryWrapper<BizProjectFeeCard>().apply("FEE_CARD_NUM =(SELECT FEE_CARD_NUM " +
                "  FROM (SELECT FEE_CARD_NUM FROM biz_project_income where ID  in("+ids.stream().map(id -> "\"" + id + "\"").collect(Collectors.joining(", "))+") " +
                "  GROUP by FEE_CARD_NUM) A GROUP by FEE_CARD_NUM HAVING COUNT(*) = 1)"));
        return baseMapper.deleteBatchIds(ids) >0;
    }


    /**
     * 根据项目id获取页面的信息
     * @param showBo
     * @return
     */
    @Override
   public ProjectIncomeShowVo getprojectInfo(FundsFeeShowBo showBo)
   {
       ProjectIncomeShowVo showVo = new ProjectIncomeShowVo();
       if(StringUtils.isNotEmpty(showBo.getProjectIncomeId())){
           BizProjectIncome come = baseMapper.selectOne(new LambdaQueryWrapper<BizProjectIncome>().eq(BizProjectIncome::getId,showBo.getProjectIncomeId()));
           BeanUtils.copyProperties(come,showVo);
           if(ObjectUtils.isNotEmpty(come.getIncomeDate())){
               showVo.setIncomeDate(LocalDate.from(come.getIncomeDate()));
           }
       }
       ClaimProjectShow projectShow = projectShowMapper.selectClaimProjectOne(new QueryWrapper<ClaimProjectShow>()
               .eq("vp.id",showBo.getProjectId()).last(" limit 1 "));
        if (ObjectUtils.isNotEmpty(projectShow)){
            showVo.setProjectId(projectShow.getProjectId());
            showVo.setProjectName(projectShow.getName());
            showVo.setFeeAuthorize(projectShow.getFeeAuthorize());
            showVo.setProjectClass(projectShow.getProjectClass());
            //没有claimid，取项目的单位，负责人
            if(StringUtils.isEmpty(showBo.getProjectIncomeId()) || StringUtils.isBlank(showBo.getProjectIncomeId())){
                showVo.setFeeChargerId(projectShow.getChargerCode());
                showVo.setUnitId(projectShow.getChargerUnitId());
                showVo.setFeeChargerCode(projectShow.getAccount());
                showVo.setFeeChargerUnitName(projectShow.getChargerUnitName());
                showVo.setFeeChargerName(projectShow.getChargerName());
            }

            BizProjectIncome claim = baseMapper.selectOne(new QueryWrapper<BizProjectIncome>()
                    .select(" sum(income_fee) as income_fee,SUM(outbound_fee) as outbound_fee")
                    .eq("project_id",showBo.getProjectId())
                    .ne(StringUtils.isNotEmpty(showBo.getProjectIncomeId()), "id", showBo.getProjectIncomeId())); //查询项目已到账金额
            BigDecimal incomeFee = BigDecimal.valueOf(0) ;//项目已到账
            BigDecimal outboundFee = BigDecimal.valueOf(0) ; //项目累计外拨
            if (ObjectUtil.isNotNull(claim)){
                incomeFee = ObjectUtils.isNotNull(claim.getIncomeFee())?claim.getIncomeFee() :incomeFee;
                outboundFee = ObjectUtils.isNotNull(claim.getOutboundFee())?claim.getOutboundFee():outboundFee;
            }
            BigDecimal outFee  = ObjectUtils.isNotNull(projectShow.getOutFee())?projectShow.getOutFee(): BigDecimal.valueOf(0);
            showVo.setNotOutFee(outFee.subtract(outboundFee)); //未外拨
            BigDecimal FeeAuthorize  = ObjectUtils.isNotNull(projectShow.getFeeAuthorize())?projectShow.getFeeAuthorize(): BigDecimal.valueOf(0);
            showVo.setNotIncomeFee(FeeAuthorize.subtract(incomeFee)); //未到账

            //新增没有卡号，取最新的卡号
            if(StringUtils.isEmpty(showVo.getFeeCardNum())){
                String cardnum = incomeService.selectIncomeFee(showBo.getProjectId(),projectShow.getChargerCode());
                showVo.setFeeCardNum(cardnum);//经费卡号
            }

            showVo.setFeeSchemeId(feeSchemeId); //默认取管理费
            List<BizManageFee> manageFeeList = new ArrayList<>();
            if(projectShow.getProjectClass().equals(project_Class_zX)){
                if(StringUtils.isNotEmpty(showBo.getProjectIncomeId())){
                    manageFeeList = manageFeeMapper.selectList(new QueryWrapper<BizManageFee>()
                            .eq("project_id", showBo.getProjectId())
                            .eq(StringUtils.isNotEmpty(showBo.getProjectIncomeId()), "income_id", showBo.getProjectIncomeId()));

                }else{
                    List<ClaimManageFeeVo> manageFeeVo= manageMapper.selectManageFeeSubjectList(new QueryWrapper<ClaimManageFeeVo>().eq("bfs.feeschemeid",feeSchemeId));
                    for(ClaimManageFeeVo claimManageFee: manageFeeVo) {
                        BizManageFee bizManageFee = new BizManageFee();
                        BeanUtils.copyProperties(claimManageFee,bizManageFee);
                        //计算总的值应该取biz_manage_fee表中的数据
                        BizManageFee manageFee =   manageFeeMapper.selectOne(new QueryWrapper<BizManageFee>().select(" sum(subject_fee) as subject_fee,subject_code")
                                .eq("project_id", showBo.getProjectId())
                                .eq("subject_code",claimManageFee.getSubjectCode())
                                .ne(StringUtils.isNotEmpty(showBo.getProjectIncomeId()), "income_id", showBo.getProjectIncomeId()));
                        bizManageFee.setSplitManageFee(ObjectUtil.isNotNull(manageFee)?manageFee.getSubjectFee(): BigDecimal.valueOf(0));
                        manageFeeList.add(bizManageFee);
                    }
                }
            }
            showVo.setManageFee(manageFeeList);
        }
       return showVo;
   }

}
